using Cysharp.Threading.Tasks;
using IQIGame.Onigao.Framework;
using System.Collections.Generic;
using UnityEngine;

namespace IQIGame.Onigao.GamePlay
{
    public class InteractJump
    {
        public bool active { get; protected set; }

        public int jumpDistance { get; protected set; }

        public int jumpHeight { get; protected set; }

        public LevelPlayRegionController regionCtrl { get; protected set; }

        public InteractStateOperational stateOperational { get; protected set; }

        public LevelPlayBaseEntity ledgeEntity { get; protected set; }

        private List<EntityParamLedgeData> _ledgeDatas = new List<EntityParamLedgeData>();

        private List<LevelPlayBaseEntity> _ledgeEntitys = new List<LevelPlayBaseEntity>();

        private float _checkTime = 0;
        private bool _isSendingJumpRequest = false;

        public InteractJump(InteractStateOperational stateOperational)
        {
            this.stateOperational = stateOperational;
            this.regionCtrl = stateOperational.regionCtrl;
        }

        public void AddFromLedgeData(EntityParamLedgeData ledgeData, LevelPlayBaseEntity entity)
        {
            this.active = true;
            _ledgeDatas.Add(ledgeData);
            _ledgeEntitys.Add(entity);
            this.jumpDistance = ledgeData.jumpDistance;
            this.jumpHeight = ledgeData.jumpHeight;
            this.ledgeEntity = entity;

#if UNITY_EDITOR
            LogGame.Log("进入跳台区域!");
#endif
        }

        public void RemoveFromLedgeData(EntityParamLedgeData ledgeData, LevelPlayBaseEntity entity)
        {
            _ledgeDatas.Remove(ledgeData);
            _ledgeEntitys.Remove(entity);
            if (_ledgeDatas.Count > 0)
            {
                ledgeData = _ledgeDatas[_ledgeDatas.Count - 1];
                entity = _ledgeEntitys[_ledgeEntitys.Count - 1];
                this.jumpDistance = ledgeData.jumpDistance;
                this.jumpHeight = ledgeData.jumpHeight;
                this.ledgeEntity = entity;
            }
            else
            {
                this.active = false;
                this._checkTime = 0;
                this._isSendingJumpRequest = false;
#if UNITY_EDITOR
                LogGame.Log("离开跳台区域!");
#endif
            }
        }

        public void Update(float deltaTime)
        {
            if (!this.active)
            {
                return;
            }
            if (!this.stateOperational.isMoving)
            {
                _checkTime = 0;
                return;
            }
            if (_isSendingJumpRequest)
            {
                return;
            }
            //判断主角当前方向是否是那个朝向
            var character = this.regionCtrl.entityCtrl.GetMainCharacter();
            var angleY = character.transform.eulerAngles.y;
            var entityAngleY = GameMathUtil.GetRotationYFromInt(this.ledgeEntity.dirEuler);

            //LogGame.LogError($"angle: {angleY} {entityAngleY}");
            if (!GameMathUtil.IsAxisRotationInRange(angleY, entityAngleY, LevelDataConsts.JumpDirRange))
            {
                _checkTime = 0;
                return;
            }

            _checkTime += deltaTime;
            if (_checkTime >= LevelDataConsts.JumpCheckTime)
            {
                _checkTime = 0;
                _isSendingJumpRequest = true;
                StartJump().Forget();
            }
        }

        private async UniTaskVoid StartJump()
        {
            //这里必须调用停止移动，该接口会同步位置给逻辑层，此后如果再次同步，只要位置没变会被忽略
            //如果不这样做，会出现问题。因为接下来的步骤是：
            //1.发送跳跃请求，逻辑层跳跃后会改变位置，过程中两边各算各的，不同步位置信息
            //2.视图层切换到跳跃状态（播放动画，改变位置），此时会离开可移动状态，而离开可移动状态时会强制停止移动并同步位置（统一规则），此时位置就错乱了（逻辑层已经跳到别的地方了）
            //但又不能先切换到跳跃状态，再发送消息，因为要先确认逻辑层的返回，只有跳跃成功才应该切换状态。
            //所以先手动停止移动，此后的同步会被忽略
            stateOperational.StopCharacterMove(true);
            //发送前重新检测是否还在跳台范围内
            if (!regionCtrl.entityCtrl.CheckInTriggerRect(ledgeEntity, true))
            {
                _isSendingJumpRequest = false;
                return;
            }
            //发送请求
            var character = this.regionCtrl.entityCtrl.GetMainCharacter();
            Vector3 dir = character.transform.forward;
            var result = await CLevelLogicModule.NetCore.CS_Jump(stateOperational.interactJump.ledgeEntity.id, dir.x, dir.z);
            if (result.IsSuccess)
            {
                //切换到跳跃状态，进行表现
                stateOperational.ChangeState(LevelInteractState.Jump);
            }
            else
            {
                LogGame.LogError("逻辑层判定跳跃失败。code：" + result.code);
            }
            _isSendingJumpRequest = false;
        }

        /// <summary>
        /// 开始跳跃
        /// </summary>
        //public async UniTaskVoid StartJump()
        //{
        //    this.stateOperational.ChangeState(LevelInteractState.Jump);

        //    LogGame.LogError("Start Jump");

        //    var character = this.levelPlayCtrl.entityCtrl.GetMainCharacter();

        //    //旋转
        //    var rotation = LevelMathUtil.Int3Quaternion(this.ledgeEntity.dirEuler);

        //    //落点
        //    var position = character.transform.position;
        //    var destPosition = LevelMathUtil.MoveInDirection(position, rotation, LevelMathUtil.LogicPosValue2Float(jumpDistance));
        //    //空中点
        //    var airPosition = destPosition;
        //    //加上高度差的最终点
        //    var logicHeight = LevelMathUtil.LogicPosValue2Float(jumpHeight);
        //    destPosition.y += logicHeight;
        //    //通过recast计算实际落点
        //    this.levelPlayCtrl.navigationCtrl.FindNearestPoint(destPosition, out var navMeshPos);

        //    //旋转到正常向
        //    await character.transform.DORotateQuaternionSpeedBase(rotation, LevelDataConsts.EntityRotationSpeed).SetLink(character.gameObject).AwaitForComplete();

        //    const float time1 = 0.6f;

        //    float time2 = logicHeight / 3f;

        //    const float time3 = 1f;

        //    //播放起跳动画
        //    character.animator.CrossFade(AnimationConst.Name_Jump_Start, 0.25f);

        //    //跳跃序列
        //    await DOTween.Sequence().SetLink(character.gameObject)
        //        .AppendInterval(0.3f)
        //        .Append(character.transform.DOMove(airPosition, time1))
        //        .Append(character.transform.DOMove(navMeshPos, LevelDataConsts.EntityJumpMoveSpeed))
        //        .AppendCallback(() => { character.animator.SetTrigger(AnimationConst.Param_JumpEnd); })
        //        .AppendInterval(time3)
        //        .AwaitForComplete();
        //    LogGame.LogError("End Jump");

        //    this.levelPlayCtrl.interactCtrl.ChangeInteractState(LevelInteractState.Operational);
        //}
    }
}
